package xiao.ze.demo.controller;

import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.support.SessionStatus;

import xiao.ze.demo.entity.User;
import xiao.ze.demo.service.UserService;

/**
 * Created by xiaozemaliya on 2017/1/31.
 */
@Controller
@SessionAttributes(value={"loginedUser"})
@RequestMapping("/security")
public class SecurityController extends BaseController{

    @Autowired
    private UserService userService ;

    @GetMapping("/toLogin")
    public String toLogin(Map<String, Object> map) throws Exception {
        Subject currentUser = SecurityUtils.getSubject();
        //如果用户已登录，先踢出
        if (currentUser.isAuthenticated()) {
            return "redirect:/security/logout";
        }
        System.out.println("进来了进来了进来了进来了进来了");
        map.put("user", new User());

        return "login";
    }

    @GetMapping("/toRegister")
    public String toRegister(Map<String, Object> map) throws Exception {

        map.put("user", new User());
        return "register";
    }

    @PostMapping(value="/login")
    public String login(@Valid User user, Errors result, Map<String, Object> map, HttpServletRequest request,
                        HttpSession session, String randomcode, String rememberMe) throws Exception {

        Subject currentUser = SecurityUtils.getSubject();

        //如果用户已登录，先踢出
        if (currentUser.isAuthenticated()) {
            return "redirect:/security/logout";
        }

        //取出session的验证码（正确的验证码）
        String validateCode = (String) session.getAttribute("validateCode");


        System.out.println(user.getUserNo()+"    "+user.getUserPwd());
        if(result.getErrorCount() > 0){
            System.out.println("出错了!");

            for(FieldError error:result.getFieldErrors()){
                System.out.println(error.getField() + ":" + error.getDefaultMessage());
            }

            return "login";

        }else if (!randomcode.equals(validateCode)){

            map.put("userError", "验证码错误");

        }else if (!currentUser.isAuthenticated()) {

            // 把用户名和密码封装为 UsernamePasswordToken 对象
            UsernamePasswordToken token = new UsernamePasswordToken(user.getUserNo(), user.getUserPwd());
            if(rememberMe!=null)
                token.setRememberMe(true);
            System.out.println(rememberMe);
            try {
                // 执行登录.
                currentUser.login(token);
                User dbUser = userService.get(user.getUserNo());
                map.put("loginedUser", dbUser);
                return "redirect:/security/mainController";
            }catch (UnknownAccountException e) {
                //unexpected condition?  error?

                System.out.println("登录失败: " + e.getMessage());
                map.put("userError", e.getMessage());

            }catch (IncorrectCredentialsException e) {
                //unexpected condition?  error?
                System.out.println("登录失败: 密码不正确");
                map.put("userError", "密码不正确");

            }
            // ... catch more exceptions here (maybe custom ones specific to your application?
            // 所有认证时异常的父类.
            catch (AuthenticationException e) {
                //unexpected condition?  error?
                System.out.println("登录失败: 账户被锁定");
                map.put("userError", e.getMessage());

            }
        }

        return "login";
    }

    @PostMapping(value="/register")
    public String register(@Valid User user, Errors result,Map<String, Object> map) throws Exception {

        try {
            User dbUser = userService.get(user.getUserNo());
            if(result.getErrorCount() > 0||dbUser!=null){
                System.out.println("出错了!");

                for(FieldError error:result.getFieldErrors()){
                    System.out.println(error.getField() + ":" + error.getDefaultMessage());
                }

                return "redirect:/security/toRegister";
            }
            userService.addUser(user);

        } catch (Exception e) {
            map.put("exceptionMessage", e.getMessage());
        }

        return "login";
    }

    @GetMapping("/mainController")
    public String main(Map<String, Object> map,User user) throws Exception{
        if(map.get("loginedUser")!=null)
            return "main";
        else{
            Subject currentUser = SecurityUtils.getSubject();
            if(currentUser.getPrincipal()!=null) {
                user=userService.get((String)currentUser.getPrincipal());
                map.put("loginedUser", user);
            }
        }
        return "main";
    }

    @GetMapping("/logout")
    public String logout(SessionStatus status) throws Exception{

        Subject currentUser = SecurityUtils.getSubject();
        if (currentUser.isAuthenticated()) {
            currentUser.logout(); // session 会销毁，在SessionListener监听session销毁，清理权限缓存
        }
        status.setComplete();
        return "redirect:/security/toLogin";

    }


}